package tcp

/**
 * A echo server to test whether the server is functioning normally
 */

 import (
	"net"
	"sync"
	"lib/sync/wait"
)

 //
 type EchoHandler struct {
	 activeConn sync.Map
	 closing 	atomic.Booleans
 }

 //Make EchoHandler
 func MakeEchoHandler *EchoHandler {
	return &EchoHandler{}
 }

 // EchoClient is client for EchoHandler
 type EchoClient struct {
	Conn 	net.Conn
	Waiting wait.Wait
}

//Close close connection
func (c *EchoClient) Close() error {
	c.Waiting.WaitWithTimeout(10 * time.Second)
	c.Conn.Close()
	return nil
}

//Handle echos received line to client
func (h *EchoHandler) Handle(ctx context.Context, conn net.Conn) {
	if h.closing.Get() {
		_ = conn.Close()
	}

	client := &EchoClient {
		Conn : conn,
	}
	h.activeConn.Store(client,struct{}{})

	reader := bufio.NewReader(conn)
	
	for {
		msg , err := reader.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				fmt.Println("connection close")
				h.activeConn.Delete(client)
			} else {
				fmt.Println(err)
			}
			return
		}
		client.Waiting.Add(1)

		b := []byte(msg)
		_,_ = conn.Write(b)
		client.Waiting.Done()
	}
}

//Close stops echo handler
func (h *EchoHandler) Close() error {
	fmt.Println("handler shutting down")
	h.closing.Set(true)
	h.activeConn.Range( func(key interface{}, val interface{}) bool {
		client := key.(*EchoClient)
		_ = client.Close()

		return true
	})
	return nil
}